Chapter 19

Baking Cookies with VBScript


CONTENTS

Put away your mixing bowl and flour. The cookies you'll learn about here have nothing to do with the edible variety. So what is a cookie? A cookie is a simple text file that is linked to a particular Web document and is stored on the client machine. "Ah," I can hear you say, "but VBScript doesn't allow you to read and write files on the client machine." In the general sense this is true, but cookies are not ordinary files.

A cookie file is a very limited ASCII text; therefore, it cannot contain any potentially harmful binary code. Furthermore, the only way that it can be written to or read from the Web is by the page that originally created it. To see the cookie files you've already collected on your travels around the Web, open your Windows Explorer and open the Cookies subdirectory within the Windows directory.

Security Issues

When cookies were first introduced, some people thought-and some still do-that the humble cookie would be a security risk. So first of all, let me put your mind at ease. Cookies cannot read information from your hard drive, nor can they publicize your personal information to the world. Here's a list of the limitations placed on cookies:

What Can You Use Cookies For?

Cookies have allowed the creation of a range of new applications, including shopping carts. This is because cookies store variables that can be used from page to page, or written and read every time a user enters a Web site. Here are just a few examples of how you could use cookies:

Cookie Variables

Cookie values are stored as name=value pairs, delimited with a semicolon (;). You can create your own variable names and assign values to them, and you can set several standard cookie variables.

domain

syntax: domain=domain_name;

When the client searches the list of cookie files, a comparison of the domain name attributes of the cookie file is made with the domain name of the host from which the Web page has been fetched. If the domain name minus the machine name (such as mcp.com) matches the stored domain name-which is known as tail matching-the cookie then performs path matching.

Only hosts within the specified domain can set a cookie for that domain, and domains must have at least two or three periods in them to prevent generic domains such as .com or .net. The default value of domain is the host name of the server that initially generated the cookie file.

path

syntax: path=path;

The path attribute is used to specify the URLs within a domain for which the particular cookie is valid. When the domain matching has been successfully completed, the pathname component of the URL is compared with the path attribute. The path
/laura would match /lauralemay and /laura/lemay.html. If a path attribute is not specified, the path is assumed to be that of the document calling the cookie.

secure

syntax: secure;

The secure attribute specifies that the cookie can be transmitted only if the communications channel with the host is a secure one. If secure is not specified, a cookie is considered safe to be sent openly, or "in the clear," over unsecured channels. However, you are dealing with client-side scripting, so the secure attribute is somewhat redundant because your VBScript cookies are never "transmitted" and remain within the client environment.

Expiration Date

syntax: expires=date;

The expiration date attribute must be written in a particular format to be recognized.

day, dd-mmm-yy hh:mm:ss GMT

Here is an example:

Thursday, 09-Oct-97 15:01:00 GMT

This poses something of a problem in VBScript, because you don't have access to a GMT date format, like you would in JavaScript. A work-around to this is to hard code an expiration date that is far into the future, say 1999. Otherwise, you will have to resort to mixing JavaScript in your document to calculate the current time offset to GMT at the client.

Baking a Temporary Cookie

A temporary cookie is one that exists only while the browser is open; when the browser is closed, the cookie is gone. This first example demonstrates how to set the value within a temporary cookie and then read back the name/value pair.

  1. Start by entering the following HTML into Notepad or your usual HTML editor:
<HTML>
<HEAD>
<TITLE>Setting a cookie [1]</TITLE>
<SCRIPT LANGUAGE="vbscript">

</SCRIPT>
<BODY BGCOLOR="white">
<CENTER>
<INPUT TYPE="button" NAME="cmdButton1" VALUE="Show Cookie Value">
</CENTER>
</BODY>
</HTML>
  1. Now you need to add the VBScript code that writes the cookie value when the page is loaded. The following code goes between the <SCRIPT> tags. Note that it is not within a custom procedure, function, or event handler; therefore, it will execute as the page downloads to the browser.
1: Dim VarName
2: Dim VarVal
3:
4: VarName = "mycookie"
5: VarVal = Date()
6:
7: Document.Cookie = VarName & "=" & VarVal & ";"

    First, in lines 1 and 2, you have declared two variables-one for the name of the cookie variable and the second for the cookie value. Lines 4 and 5 assign values to these variables. The cookie variable has been given the name mycookie. The value is taken from the client machine's date. Finally, in line 7, the Document's Cookie property is set by building a string made up of the Cookie variable's name, an equal sign, the cookie value, and a semicolon.
  1. To finish, you need to add an event handler for cmdButton1, which will be used to display the name/value pair from the cookie.
Sub cmdButton1_OnClick
  Alert Document.Cookie
End Sub

As you can see, it's frighteningly easy. All you have to do in this case is pass the Document.Cookie property to an Alert box.

Here's the complete code for this example. To use this demonstration, you need to load the HTML file onto a Web server and run it from there. Cookies don't appear to like being run from a local drive. Figure 19.1 shows this example running from the test subdirectory of my vbscripts.com domain.

Figure 19.1 : The cookie name/value pair.

<HTML>
<HEAD>
<TITLE>Setting a cookie [1]</TITLE>
<SCRIPT LANGUAGE="vbscript">
Dim VarName
Dim VarVal

VarName = "mycookie"
VarVal = Date()

Document.Cookie = VarName & "=" & VarVal & ";"

Sub cmdButton1_OnClick
  Alert Document.Cookie
End Sub

</SCRIPT>
<BODY BGCOLOR="white">
<CENTER>
<INPUT TYPE="button" NAME="cmdButton1" VALUE="Show Cookie Value">
</CENTER>
</BODY>
</HTML>

When you have run this example, take a look in the Cookies subdirectory, just to prove to yourself that the cookie hasn't been written to disk. To write a cookie to disk, all you need to do is add an expiration date.

Baking a Semi-Permanent Cookie

This example demonstrates how to create a semi-permanent cookie file. I use the term semi-permanent because there is no such thing as a permanent cookie file. By its very nature, a cookie can be written to disk only if it has been given an expiration date. However, by setting the date to a time in the distant future, you can give the cookie some semi-permanence.

  1. Start again with your HTML template.
<HTML>
<HEAD>
<TITLE>Setting a cookie [2]</TITLE>
<SCRIPT LANGUAGE="vbscript">

</SCRIPT>
<BODY BGCOLOR="white">
<CENTER>
<INPUT TYPE="button" NAME="cmdButton1" VALUE="Get Cookie Value">
</CENTER>
</BODY>
</HTML>
  1. Now add the following code between the <SCRIPT> tags to create the cookie. Notice that it is very similar to the previous example, with the addition of an expiration variable.
Dim VarName
Dim VarVal
Dim Exp

Exp = "expires=Wednesday, 09-Nov-1999 23:12:40 GMT"
VarName = "mycookie"
VarVal = Date()

Document.Cookie = VarName & "=" & VarVal & ";" & Exp

    The easiest way to specify an expiration date is to specify it explicitly, as shown in the preceding code. It must be specified in this format, which involves an awful lot of extra coding if, for example, you want to specify an expiration date based on the current date.
  1. Finally, add the same event handler as before to show the cookie's name/value pair.
Sub cmdButton1_OnClick
 Alert Document.Cookie
End Sub

Here's the completed code:

<HTML>
<HEAD>
<TITLE>Setting a cookie [2]</TITLE>
<SCRIPT LANGUAGE="vbscript">
Dim VarName
Dim VarVal
Dim Exp

Exp = "expires=Wednesday, 09-Nov-1999 23:12:40 GMT"
VarName = "mycookie"
VarVal = Date()

Document.Cookie = VarName & "=" & VarVal & ";" & Exp

Sub cmdButton1_OnClick
 Alert Document.Cookie
End Sub

</SCRIPT>
<BODY BGCOLOR="white">
<CENTER>
<INPUT TYPE="button" NAME="cmdButton1" VALUE="Get Cookie Value">
</CENTER>
</BODY>
</HTML>

Again, this example executes properly only from a Web server, as shown in Figure 19.2. This time when you have run the page, you should find a new cookie file in your Cookies subdirectory. You can open the file (for what it's worth) in Notepad, as shown in Figure 19.3.

Figure 19.2 : The bake2.htm file in the browser.

Figure 19.3 : The resultant cookie file.

Baking a Cookie with Multiple Values

The previous two examples have used a single variable. Now you can try creating a cookie file that stores multiple values:

  1. Start with the HTML template.
<HTML>
<HEAD>
<TITLE>Setting a cookie [3]</TITLE>
<SCRIPT LANGUAGE="vbscript">

</SCRIPT>
<BODY BGCOLOR="white">
<CENTER>
<INPUT TYPE="button" NAME="cmdButton1" VALUE="Get Cookie Value">
</CENTER>
</BODY>
</HTML>
  1. Add the following code between the <SCRIPT> tags:
 1: Dim VarName
 2: Dim VarVal
 3: Dim VarName1
 4: Dim VarVal1
 5: Dim Exp
 6:
 7: Exp = "expires=Wednesday, 09-Nov-1999 23:12:40 GMT"
 8: VarName = "mycookie"
 9: VarVal = Date()
10: VarName1 = "nextname"
11: VarVal1 = "anything;"
12:
13: Document.Cookie = VarName & "=" & VarVal & ";"
& VarName1 & "=" & VarVal1 & Exp

    Notice that in this example the semicolon that delimits the second value is attached to the string as part of the second value.
  1. Again, add the event handler for the button, which displays the two
    name/value pairs as shown in Figure 19.4.

Figure 19.4 : The two name/value pairs are now displayed.

Sub cmdButton1_OnClick
 Alert Document.Cookie
End Sub

Here's the complete code for the multiple value example. You can add as many name/value pairs as you require, up to a maximum total cookie size of 4KB.

<HTML>
<HEAD>
<TITLE>Setting a cookie [3]</TITLE>
<SCRIPT LANGUAGE="vbscript">
Dim VarName
Dim VarVal
Dim VarName1
Dim VarVal1
Dim Exp

Exp = "expires=Wednesday, 09-Nov-1999 23:12:40 GMT"
VarName = "mycookie"
VarVal = Date()
VarName1 = "nextname"
VarVal1 = "anything;"

Document.Cookie = VarName & "=" & VarVal & ";" & VarName1 & "=" & VarVal1 & Exp

Sub cmdButton1_OnClick
 Alert Document.Cookie
End Sub

</SCRIPT>
<BODY BGCOLOR="white">
<CENTER>
<INPUT TYPE="button" NAME="cmdButton1" VALUE="Get Cookie Value">
</CENTER>
</BODY>
</HTML>

Reading Individual Cookie Values

In the real world, you need to get hold of individual cookie values rather than the complete cookie or a name/value pair. This requires you to get involved in manipulating the string that is returned by Document.Cookie.

The string that is returned is the complete cookie-basically, a series of name/value pairs delimited by semicolons. Therefore, you need to find the variable name within the string, and from its position in the string, you can then extract the value associated with that variable. This example shows you how to dissect the cookie string in order to return the value of a specific variable within the cookie.

The HTML template for this example is slightly different from the ones used before. For ease of demonstration, each of the two variables within the cookie will be returned by clicking on the appropriate button.

<HTML>
<HEAD>
<TITLE>Getting a Cookie</TITLE>
<SCRIPT LANGUAGE="vbscript">

</SCRIPT>
<BODY BGCOLOR="white">
<CENTER>
<INPUT TYPE="button" NAME="cmdButton1" VALUE="Get MyCookie Value">
<P>
<INPUT TYPE="button" NAME="cmdButton2" VALUE="Get NextName Value">
</CENTER>
</BODY>
</HTML>

When you've entered the HTML template, between the <SCRIPT> tags add the following two event handlers for the two buttons. Note that each one calls the same custom procedure, passing the name of the variable to be returned.

Sub cmdButton1_OnClick
 Call GetCookieValue("mycookie")
End Sub

Sub cmdButton2_OnClick
 Call GetCookieValue("nextname")
End Sub

Now you can enter the custom procedure. Again, the line numbers are only for ease of explanation.

 1: Sub GetCookieValue(CkName)
 2:
 3:  CkNameLen = Len(CkName)
 4:
 5:  If InStr(Document.Cookie, CkName) = 0 Then
 6:   Alert "Cookie value not found"
 7:  Else
 8:   CkValStart = InStr(Document.Cookie, CkName) + CkNameLen + 1
 9:
10:    If InStr(CkValStart, Document.Cookie, ";") = 0 Then
11:     CkVal = Mid(Document.Cookie, CkValStart)
12:    Else
13:     CkValEnd = InStr(CkValStart, Document.Cookie, ";")
14:     CkValLen = CkValEnd - CkValStart
15:     CkVal = Mid(Document.Cookie, CkValStart, CkValLen)
16:    End If
17:
18:   Alert CkVal
19:  End If
20: End Sub

The custom procedure prototype is on line 1, and it requires that the name of the cookie variable be passed into the procedure when it is called. The length of the name string is obtained and assigned to the variable CkNameLen in line 3.

Line 5 checks to make sure that the variable name is present within the cookie string. If it is not, a warning message is displayed and the procedure is terminated.

If the variable name is found within the cookie string, execution continues at line 8, where the position of the first character of the variable value is calculated. This is done by adding the length of the variable name to the start position of the variable name to give the end position of the variable name. Then you add one further character to basically jump past the = that sits between the variable name and the variable value.

If the variable value that you are seeking is the last one in the cookie, the semicolon will not appear after the value. Therefore, line 10 checks to see whether a semicolon is present at some point after the start of the variable value. If not, this is the last value of the cookie, and its end point can be taken as the end point of the overall cookie. If there is a semicolon present after the variable value, the position of the semicolon is the end point of the variable value.

The Mid function used in line 11 does not use a string length element and, therefore, Mid returns a string that ends at the last character of the source string. The Mid function in line 15 uses the calculated length of the value string to pluck the value from the source string.

Here's the complete source code for the example. The results of clicking the two buttons are shown in Figures 19.5 and 19.6.

Figure 19.5 : Click the MyCookie button to return the value of the mycookie variable.

Figure 19.6 : Click the NextName button to return the value of the nextname variable.

<HTML>
<HEAD>
<TITLE>Getting a Cookie</TITLE>
<SCRIPT LANGUAGE="vbscript">

Sub cmdButton1_OnClick
 Call GetCookieValue("mycookie")
End Sub

Sub cmdButton2_OnClick
 Call GetCookieValue("nextname")
End Sub

Sub GetCookieValue(CkName)

 CkNameLen = Len(CkName)

 If InStr(Document.Cookie, CkName) = 0 Then
  Alert "Cookie value not found"
 Else
  CkValStart = InStr(Document.Cookie, CkName) + CkNameLen + 1

   If InStr(CkValStart, Document.Cookie, ";") = 0 Then
    CkVal = Mid(Document.Cookie, CkValStart)
   Else
    CkValEnd = InStr(CkValStart, Document.Cookie, ";")
    CkValLen = CkValEnd - CkValStart
    CkVal = Mid(Document.Cookie, CkValStart, CkValLen)
   End If

  Alert CkVal
 End If
End Sub

</SCRIPT>
<BODY BGCOLOR="white">
<CENTER>
<INPUT TYPE="button" NAME="cmdButton1" VALUE="Get MyCookie Value">
<P>
<INPUT TYPE="button" NAME="cmdButton2" VALUE="Get NextName Value">
</CENTER>
</BODY>
</HTML>

Workshop Wrap-Up

Cookies represent an important aspect of interactive Web development. Most people are coming to realize that, far from being a threat to their privacy, cookies have been developed to enhance the surfing experience by allowing site designers to personalize Web sites. The security argument is further diminished with client-side scripting, because the cookie file never leaves the client machine.

You can find more general information about cookies at this Netscape site:

http://home.netscape.com/newsref/std/cookie_spec.html

You can also find an excellent Web page, called Andy's Netscape HTTP Cookie Info, at this address:

http://www.illuminatus.com/cookie.fcgi

Next Steps

Now that you've seen how cookies work and how you bake them to create wonderfully tasty Web pages, why not add some of the following VBScript flavorings to your recipe?

Q&A

Q:
Why are cookies called cookies?
A:
I've never seen a definitive answer to this one. Cookies were originally referred to as Magic Cookies. The most plausible explanation I have read is that they were so named after Dan O'Neill's book, Hear the Sound of My Feet Walking... Drown the Sound of My Voice Talking... In the book, Fred gives Hugh and Sam magic cookies and watches their interactive Magic Cookie Land dreams; then Fred uses a magic cookie himself to get into Hugh's dream. (Like you would, I suppose!)
This relates to cookies because Fred symbolizes the webmaster, and dreams represent browsing or surfing. Maybe now you can see where the idea for the name came from, although "watching" would be a gross exaggeration of the purpose and use of cookies.